﻿using System;

namespace SapaFinance.Domain.Model
{
    public class Money : AbstractEntity
    {
        protected Money() {}

        public Money(decimal amount, Currency currency)
            : this()
        {
            Amount = amount;
            Currency = currency;
        }

        public virtual decimal Amount { get; private set; }
        public virtual Currency Currency { get; private set; }

        public static Money Create(decimal amount, Currency currency)
        {
            Object[] args = {amount, currency};
            return (Money) Activator.CreateInstance(typeof (Money), args);
        }

        public static Money operator +(Money m1, Money m2)
        {
            if (m1.Currency.Equals(m2.Currency))
                return Create(m1.Amount + m2.Amount, m1.Currency);
            throw new InvalidOperationException("Can't exec math operation under different type class");
        }

        public static Money operator *(Money m1, Money m2)
        {
            if (m1.Currency.Equals(m2.Currency))
                return Create(m1.Amount*m2.Amount, m1.Currency);
            throw new InvalidOperationException("Can't exec math operation under different type class");
        }
        public static Money operator /(Money m1, Money m2)
        {
            if (m1.Currency.Equals(m2.Currency))
                return Create(m1.Amount/m2.Amount, m1.Currency);
            throw new InvalidOperationException("Can't exec math operation under different type class");
        }
        public static Money operator -(Money m1, Money m2)
        {
            if (m1.Currency.Equals(m2.Currency))
                return Create(m1.Amount - m2.Amount, m1.Currency);
            throw new InvalidOperationException("Can't exec math operation under different type class");
        }

        public static bool operator ==(Money m1, Money m2)
        {
            return (m1.Equals(m2));
        }

        public static bool operator >(Money m1, Money m2)
        {
            if (m1.Currency.Equals(m2.Currency))
                return m1.Amount > m2.Amount;
            throw new InvalidOperationException("Can't exec math operation under different type class");
        }

        public static bool operator <(Money m1, Money m2)
        {
            if (m1.Currency.Equals(m2.Currency))
                return m1.Amount < m2.Amount;
            throw new InvalidOperationException("Can't exec math operation under different type class");
        }
        public static bool operator <=(Money m1, Money m2)
        {
            if (m1.Currency.Equals(m2.Currency))
                return m1.Amount <= m2.Amount;
            throw new InvalidOperationException("Can't exec math operation under different type class");
        }
        public static bool operator >=(Money m1, Money m2)
        {
            if (m1.Currency.Equals(m2.Currency))
                return m1.Amount >= m2.Amount;
            throw new InvalidOperationException("Can't exec math operation under different type class");
        }

        public static bool operator !=(Money m1, Money m2)
        {
            return !(m1 == m2);
        }

        public override bool Equals(object obj)
        {
            var compare = (Money) obj;
            if (ReferenceEquals(null, compare)) return false;
            return Amount == compare.Amount && compare.Currency.Equals(Currency);
        }
    }
}